import java.io.IOException;
import java.net.DatagramSocket;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

/**
 * Wrapper class for DatagramSocket. Able to send an object directly.
 * 
 * @author Jiabin
 * 
 */
public class UDPWrapper
{
    private DatagramSocket socket;

    public UDPWrapper()
    {
        try
        {
            socket = new DatagramSocket();
        }
        catch (SocketException e)
        {
            System.err.println("UDP socket binding failed!");
            e.printStackTrace();
        }
    }

    public UDPWrapper(int port) throws SocketException
    {
        this.bind(port);
    }

    private void bind(int port) throws SocketException
    {
        if (socket != null)
            socket.close();

        socket = new DatagramSocket(port);
    }

    public void send(Object obj, String dstIP, int dstPort)
    {
        byte[] data = Utility.serializeObj(obj);
        InetAddress addr = Utility.buildInetAddr(dstIP);

        DatagramPacket packet = new DatagramPacket(data, data.length, addr, dstPort);

        try
        {
            System.out.println("Message sent from Node (Port " + socket.getLocalPort() + ") to Node (Port " + dstPort
                    + ")");
            socket.send(packet);
        }
        catch (IOException e)
        {
            System.err.println("Error when sending object.");
            e.printStackTrace();
        }
    }

    public void receive(DatagramPacket packet)
    {
        try
        {
            socket.receive(packet);
            System.out.println("Message received at Node (Port " + socket.getLocalPort() + ") from Node (Port "
                    + packet.getPort() + ")");
        }
        catch (IOException e)
        {
            System.err.println("Error when receiving.");
            e.printStackTrace();
        }
    }

    public void close()
    {
        socket.close();
    }
}
